//@version=5
// © HancoLab 2025
strategy("[HancoLab] GPT가 만든 전략", overlay=true, 
  default_qty_type = strategy.percent_of_equity, default_qty_value = 2, 
  initial_capital = 10000, currency = currency.USD, pyramiding = 1, commission_type = strategy.commission.percent, commission_value = 0.06)

// =====================
// == 1) Inputs
// =====================
res_tf            = input.timeframe("60", "Timeframe (for reference)", group="General")
ema_len           = input.int(20, "EMA (short) length", minval=1, group="Trend")
sma_len           = input.int(50, "SMA (mid) length", minval=1, group="Trend")
rsi_len           = input.int(14, "RSI length", minval=1, group="Momentum")
rsi_thresh_mid    = input.int(50, "RSI center threshold", group="Momentum")
adx_len           = input.int(14, "ADX length", minval=1, group="ADX")
adx_thresh        = input.int(25, "ADX threshold (trend strength)", group="ADX")
atr_len           = input.int(14, "ATR length", minval=1, group="Volatility")
sl_atr_mult       = input.float(3.0, "Stop-loss (ATR x)", step=0.1, group="Volatility")
tp_atr_mult       = input.float(2.0, "Initial TP (ATR x)", step=0.1, group="Volatility")
trail_enable      = input.bool(true, "Enable ATR trailing stop", group="Volatility")
trail_atr_mult    = input.float(1.5, "Trailing ATR multiplier", step=0.1, group="Volatility")
max_positions     = input.int(1, "Pyramiding (max entries)", minval=1, group="General")
commission_pct    = input.float(0.06, "Commission % (per trade)", step=0.01, group="General")
slippage_ticks    = input.float(0.0, "Simulated slippage (ticks)", group="General")
show_labels       = input.bool(true, "Show entry/exit labels", group="General")
leverage_display  = input.int(10, "Simulated leverage (display only)", minval=1, group="General")

// =====================
// == 2) Helper: custom ADX implementation (returns adx, plusDI, minusDI)
// =====================
f_adx(_len) =>
    // Calculate directional movement
    up = high - high[1]
    down = low[1] - low
    plusDM = (up > down and up > 0) ? up : 0.0
    minusDM = (down > up and down > 0) ? down : 0.0
    // True range
    tr = math.max(math.max(high - low, math.abs(high - close[1])), math.abs(low - close[1]))
    // Wilders smoothing using rma (rma is Wilder's moving average)
    smTR = ta.rma(tr, _len)
    smPlus = ta.rma(plusDM, _len)
    smMinus = ta.rma(minusDM, _len)
    // DI and DX
    plusDI = (smTR != 0) ? 100 * (smPlus / smTR) : 0.0
    minusDI = (smTR != 0) ? 100 * (smMinus / smTR) : 0.0
    dx = (plusDI + minusDI) != 0 ? 100 * math.abs(plusDI - minusDI) / (plusDI + minusDI) : 0.0
    adx = ta.rma(dx, _len)
    [adx, plusDI, minusDI]

// =====================
// == 3) Indicators & signals
// =====================
emaShort = ta.ema(close, ema_len)
smaMid   = ta.sma(close, sma_len)
rsiVal   = ta.rsi(close, rsi_len)
[adxVal, plusDI, minusDI] = f_adx(adx_len)
atrVal   = ta.atr(atr_len)

// Trend logic
ema_above_sma = emaShort > smaMid
ema_below_sma = emaShort < smaMid

// Entry conditions
longCondition = ta.crossover(close, emaShort) and ema_above_sma and rsiVal > rsi_thresh_mid and (adxVal > adx_thresh) and (plusDI > minusDI)
shortCondition = ta.crossunder(close, emaShort) and ema_below_sma and rsiVal < rsi_thresh_mid and (adxVal > adx_thresh) and (minusDI > plusDI)

// =====================
// == 4) Risk math: stop / tp calculation
// =====================
long_sl_price  = strategy.position_size == 0 ? (close - sl_atr_mult * atrVal) : na
long_tp_price  = strategy.position_size == 0 ? (close + tp_atr_mult * atrVal) : na
short_sl_price = strategy.position_size == 0 ? (close + sl_atr_mult * atrVal) : na
short_tp_price = strategy.position_size == 0 ? (close - tp_atr_mult * atrVal) : na

// Slight slippage adjustment (in price units)
tick = syminfo.mintick
_slippage = slippage_ticks * tick

// =====================
// == 5) Entries & Exits (single-level entry with fixed SL/TP + optional trailing)
// =====================
// Place long entry
if (longCondition)
    strategy.entry("Long", strategy.long, comment="Long Entry")

// Place short entry
if (shortCondition)
    strategy.entry("Short", strategy.short, comment="Short Entry")

// Exit management after entry: attach stoploss & takeprofit via strategy.exit
// We use different exits for long/short to attach SL/TP/Trail.
if (strategy.position_size > 0)
    // Current position is long
    entry_price = strategy.position_avg_price
    sl = entry_price - sl_atr_mult * atrVal - _slippage
    tp = entry_price + tp_atr_mult * atrVal + _slippage
    if (trail_enable)
        // trailing stop based on ATR: trail by trail_atr_mult * ATR from the highest price since entry
        strategy.exit(id="Exit Long", from_entry="Long", stop = sl, limit = tp, trail_points = na, trail_offset = trail_atr_mult * atrVal)
    else
        strategy.exit(id="Exit Long", from_entry="Long", stop = sl, limit = tp)

// Short side
if (strategy.position_size < 0)
    entry_price = strategy.position_avg_price
    sl = entry_price + sl_atr_mult * atrVal + _slippage
    tp = entry_price - tp_atr_mult * atrVal - _slippage
    if (trail_enable)
        strategy.exit(id="Exit Short", from_entry="Short", stop = sl, limit = tp, trail_points = na, trail_offset = trail_atr_mult * atrVal)
    else
        strategy.exit(id="Exit Short", from_entry="Short", stop = sl, limit = tp)

// =====================
// == 6) Plotting & info
// =====================
plot(emaShort, title="EMA Short", linewidth=2)
plot(smaMid, title="SMA Mid", linewidth=1)
hline(adx_thresh, "ADX threshold", color=color.gray, linestyle=hline.style_dotted)
plot(adxVal, title="ADX", color = color.orange, linewidth=1, display=display.none)  // hidden by default
plotshape(longCondition and show_labels ? low : na, title="LongEntry", location=location.belowbar, style=shape.labelup, text="Long", size=size.tiny, color=color.green)
plotshape(shortCondition and show_labels ? high : na, title="ShortEntry", location=location.abovebar, style=shape.labeldown, text="Short", size=size.tiny, color=color.red)

// Info box
var table info = table.new(position.top_right, 1, 6, border_width = 1)
if barstate.islast
    table.cell(info, 0, 0, "EMA"+str.tostring(ema_len)+" > SMA"+str.tostring(sma_len)+" ? " + (ema_above_sma ? "YES" : "NO"))
    table.cell(info, 0, 1, "RSI: " + str.tostring(rsiVal, format.percent))
    table.cell(info, 0, 2, "ADX: " + str.tostring(adxVal, format.percent) + " (th=" + str.tostring(adx_thresh) + ")")
    table.cell(info, 0, 3, "ATR: " + str.tostring(atrVal, format.mintick))
    table.cell(info, 0, 4, "Leverage (sim): " + str.tostring(leverage_display) + "x")
    table.cell(info, 0, 5, "Commission: " + str.tostring(commission_pct) + "%")

// End of script